package com.handinglian.task.service.impl;

import cn.afterturn.easypoi.entity.vo.NormalExcelConstants;
import cn.afterturn.easypoi.excel.ExcelImportUtil;
import cn.afterturn.easypoi.excel.entity.ExportParams;
import cn.afterturn.easypoi.excel.entity.ImportParams;
import cn.afterturn.easypoi.excel.entity.enmus.ExcelType;
import cn.afterturn.easypoi.view.PoiBaseView;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.StrUtil;
import com.handinglian.common.dto.CommonPage;
import com.handinglian.common.enums.ValidEnum;
import com.handinglian.common.utils.DateUtil;
import com.handinglian.common.utils.FastJsonUtil;
import com.handinglian.common.utils.GeneralUtil;
import com.handinglian.common.utils.StringUtil;
import com.handinglian.employee.dto.DepartmentDto;
import com.handinglian.employee.dto.UserTagDto;
import com.handinglian.employee.entity.UserInfo;
import com.handinglian.employee.service.DepartmentService;
import com.handinglian.employee.service.UserInfoService;
import com.handinglian.employee.service.UserTagService;
import com.handinglian.servicerecord.dto.TaskIndexDto;
import com.handinglian.servicerecord.entity.CallRecord;
import com.handinglian.servicerecord.service.CallRecordService;
import com.handinglian.servicerecord.service.MessageService;
import com.handinglian.task.dto.*;
import com.handinglian.task.entity.*;
import com.handinglian.task.enums.CalllStateEnum;
import com.handinglian.task.enums.PhoneStateEnum;
import com.handinglian.task.enums.TaskStateEnum;
import com.handinglian.task.mapper.TaskInfoMapper;
import com.handinglian.task.param.TaskInfoCreateParam;
import com.handinglian.task.param.TaskInfoUpdateParam;
import com.handinglian.task.service.*;
import com.handinglian.thirdparty.YunqixunApiService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Async;
import org.springframework.scheduling.annotation.AsyncResult;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.ui.ModelMap;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.math.BigDecimal;
import java.util.*;
import java.util.concurrent.Future;
import java.util.stream.Collectors;


@Service("taskInfoService")
public class TaskInfoServiceImpl implements TaskInfoService {
    @Autowired
    private TaskInfoMapper taskInfoMapper;
    @Autowired
    private TaskUserRelationService taskUserRelationService;
    @Autowired
    private TaskUserMessageService taskUserMessageService;
    @Autowired
    private TaskUserNoteService taskUserNoteService;
    @Autowired
    private TaskUserCallService taskUserCallService;
    @Autowired
    private CallRecordService callRecordService;
    @Autowired
    private UserInfoService userInfoService;
    @Autowired
    private UserTagService userTagService;
    @Autowired
    private YunqixunApiService yunqixunApiService;
    @Autowired
    private MessageService messageService;
    @Autowired
    private DepartmentService departmentService;

    @Override
    @Transactional
    public Integer createTaskInfo(TaskInfoCreateParam taskInfoCreateParam, Integer userId) {
        String startDate = taskInfoCreateParam.getStartDate()+" 00:00:00";
        String endDate = taskInfoCreateParam.getEndDate()+" 23:59:59";
        Date now = new Date();
        TaskInfo taskInfo = FastJsonUtil.ObjectToObject(taskInfoCreateParam, TaskInfo.class);
        taskInfo.setStartDate(cn.hutool.core.date.DateUtil.parseDateTime(startDate));
        taskInfo.setEndDate(cn.hutool.core.date.DateUtil.parseDateTime(endDate));
        taskInfo.setCreateTime(now);
        taskInfo.setUpdateTime(now);
        taskInfo.setUserId(userId);
        taskInfoMapper.insertSelective(taskInfo);
        return taskInfo.getTaskId();
    }

    @Override
    @Transactional
    public int updateTaskInfo(TaskInfoUpdateParam taskInfoUpdateParam) {
        String startDate = taskInfoUpdateParam.getStartDate()+" 00:00:00";
        String endDate = taskInfoUpdateParam.getEndDate()+" 23:59:59";
        TaskInfo taskInfo = FastJsonUtil.ObjectToObject(taskInfoUpdateParam, TaskInfo.class);
        taskInfo.setStartDate(cn.hutool.core.date.DateUtil.parseDateTime(startDate));
        taskInfo.setEndDate(cn.hutool.core.date.DateUtil.parseDateTime(endDate));
        taskInfo.setUpdateTime(new Date());
        return taskInfoMapper.updateByPrimaryKeySelective(taskInfo);
    }

    @Override
    @Transactional
    public int deleteTaskInfo(Integer taskId) {
        taskUserRelationService.deleteTaskUserByTaskId(taskId);
        return taskInfoMapper.deleteByPrimaryKey(taskId);
    }

    @Override
    public TaskInfoDetailDto loadTaskInfoDetail(Integer taskId) {
        List<TaskUserRelation> taskUserRelations = taskUserRelationService.inquireTaskUserByTaskId(taskId);
        return loadDetail(taskUserRelations, taskId);
    }

    @Override
    public TaskInfoDetailDto getDetailApp(Integer userId, Integer taskId) {
        List<TaskUserRelation> taskUserRelations = taskUserRelationService.list(taskId, userId);
        return loadDetail(taskUserRelations, taskId);
    }

    private TaskInfoDetailDto loadDetail(List<TaskUserRelation> taskUserRelations, Integer taskId) {
        TaskInfo taskInfo = taskInfoMapper.selectByPrimaryKey(taskId);
        DepartmentDto departmentDto = departmentService.loadDepartment(taskInfo.getDepartmentId());
        TaskInfoDetailDto taskInfoDetailDto = FastJsonUtil.ObjectToObject(taskInfo, TaskInfoDetailDto.class);
        taskInfoDetailDto.setDepartmentName(departmentDto.getDepartmentName());
        List<Integer> taskIds = taskUserRelations.stream().map(taskUserRelation -> taskUserRelation.getTaskId()).collect(Collectors.toList());
        List<Integer> taskUserIds = taskUserRelations.stream().map(taskUserRelation -> taskUserRelation.getTaskUserId()).collect(Collectors.toList());
        //设置任务标志
        if (taskIds.size() == 0) {
            taskInfoDetailDto.setTaskState(TaskStateEnum.READY_ASSIGN.getKey());
        } else {
            Date now = new Date();
            if (now.getTime() < taskInfoDetailDto.getStartDate().getTime()) {
                taskInfoDetailDto.setTaskState(TaskStateEnum.READY_START.getKey());
            } else if (now.getTime() >= taskInfoDetailDto.getStartDate().getTime() && now.getTime() <= taskInfoDetailDto.getEndDate().getTime()) {
                taskInfoDetailDto.setTaskState(TaskStateEnum.EXECUTORY.getKey());
            } else {
                taskInfoDetailDto.setTaskState(TaskStateEnum.OVERDUE.getKey());
            }
        }

        //客户经理数量、客户数量、查询员工呼叫、呼通客户数量
        Set<String> customerPhones = taskUserRelations.stream().map(taskUserRelation -> taskUserRelation.getCustomerPhone()).collect(Collectors.toSet());
        Set<Integer> userIds = taskUserRelations.stream().map(taskUserRelation -> taskUserRelation.getUserId()).collect(Collectors.toSet());
        Integer callNum = 0;
        Integer answerNum = 0;
        if (CollUtil.isNotEmpty(taskUserIds)) {
            callNum = callRecordService.countTaskCallNum(taskUserIds);
            answerNum = callRecordService.countTaskAnswerNum(taskUserIds);
        }

        UserInfo userInfo = userInfoService.get(taskInfoDetailDto.getUserId());
        taskInfoDetailDto.setUserName(userInfo.getUserName());
        taskInfoDetailDto.setEmployeeNum(userIds.size());
        taskInfoDetailDto.setCustomerNum(customerPhones.size());
        taskInfoDetailDto.setCallNum(callNum);
        taskInfoDetailDto.setAnswerNum(answerNum);

        return taskInfoDetailDto;
    }

    @Override
    public CommonPage<TaskInfoDto> inquireTaskInfoPageList(Integer userId, String titleOrDesc, String startDate, String endDate, String sortField, String sortOrder, String taskStates, Integer pageIndex, Integer pageSize) {
        UserInfo userInfo = userInfoService.get(userId);
        List<Integer> departmentIds = null;
        if (!userInfo.getJobNum().equals("admin")) {
            String dataList = userInfo.getDataList();
            departmentIds = StringUtil.stringToIntegerList(dataList);
        }
        pageIndex = pageIndex == null ? 1 : pageIndex;
        pageSize = pageSize == null ? 10 : pageSize;
        startDate = startDate + " 00:00:00";
        endDate = endDate + " 23:59:59";
        List<TaskInfoDto> taskInfoDtos = taskInfoMapper.findTaskInfo(titleOrDesc, DateUtil.from(startDate), DateUtil.from(endDate), sortField, sortOrder, departmentIds);
        CommonPage<TaskInfoDto> productDtos = CommonPage.restPage(taskInfoDtos);

        List<Integer> taskIds = taskUserRelationService.getTaskId();

        //对任务标志进行置值
        taskInfoDtos.forEach(taskInfoDto -> {
            if (!taskIds.contains(taskInfoDto.getTaskId())) {
                taskInfoDto.setTaskState(TaskStateEnum.READY_ASSIGN.getKey());
            } else {
                Date now = new Date();
                if (now.getTime() < taskInfoDto.getStartDate().getTime()) {
                    taskInfoDto.setTaskState(TaskStateEnum.READY_START.getKey());
                } else if (now.getTime() >= taskInfoDto.getStartDate().getTime() && now.getTime() <= taskInfoDto.getEndDate().getTime()) {
                    taskInfoDto.setTaskState(TaskStateEnum.EXECUTORY.getKey());
                } else {
                    taskInfoDto.setTaskState(TaskStateEnum.OVERDUE.getKey());
                }
            }
        });

        List<Integer> stateList = StringUtil.stringToIntegerList(taskStates);
        List<TaskInfoDto> taskInfoAll = new ArrayList<>();
        for (Integer taskState : stateList) {
            List<TaskInfoDto> tempList = new ArrayList<>();
            //筛选任务
            if (TaskStateEnum.EXECUTORY.getKey().equals(taskState)) {
                tempList = taskInfoDtos.stream().filter(taskInfoDto -> taskInfoDto.getTaskState().equals(TaskStateEnum.EXECUTORY.getKey())).collect(Collectors.toList());
            } else if (TaskStateEnum.OVERDUE.getKey().equals(taskState)) {
                tempList = taskInfoDtos.stream().filter(taskInfoDto -> taskInfoDto.getTaskState().equals(TaskStateEnum.OVERDUE.getKey())).collect(Collectors.toList());
            } else if (TaskStateEnum.READY_ASSIGN.getKey().equals(taskState)) {
                tempList = taskInfoDtos.stream().filter(taskInfoDto -> taskInfoDto.getTaskState().equals(TaskStateEnum.READY_ASSIGN.getKey())).collect(Collectors.toList());
            } else if (TaskStateEnum.READY_START.getKey().equals(taskState)) {
                tempList = taskInfoDtos.stream().filter(taskInfoDto -> taskInfoDto.getTaskState().equals(TaskStateEnum.READY_START.getKey())).collect(Collectors.toList());
            }
            taskInfoAll.addAll(tempList);
        }
        //状态为空则全选
        if (stateList.size() == 0) {
            taskInfoAll.addAll(taskInfoDtos);
        }

        Integer total = taskInfoAll.size();
        Integer pages = total <= pageSize ? 1 : (total / pageSize == 0 ? total / pageSize : total / pageSize + 1);
        if (total > pageSize && total >= pageIndex * pageSize) {
            taskInfoAll = taskInfoAll.subList((pageIndex - 1) * pageSize, pageIndex * pageSize);
        } else if (total > pageSize && total < pageIndex * pageSize) {
            taskInfoAll = taskInfoAll.subList((pageIndex - 1) * pageSize, taskInfoAll.size());
        }

        productDtos.setTotal(Long.valueOf(total));
        productDtos.setPages(pages);
        productDtos.setPageNum(pageIndex);
        productDtos.setPageSize(pageSize);
        productDtos.setList(taskInfoAll);
        return productDtos;
    }

    @Override
    public boolean hasTask(Integer userId) {
        List<TaskUserRelation> taskUserRelations = taskUserRelationService.list(userId);
        List<Integer> taskIds = taskUserRelations.stream().map(taskUserRelation -> taskUserRelation.getTaskId()).distinct().collect(Collectors.toList());
        if (CollUtil.isEmpty(taskIds)) {
            return false;
        }

        List<TaskInfo> taskInfos = taskInfoMapper.findByTaskIdIn(taskIds);
        List<TaskInfoDto> taskInfoDtos = FastJsonUtil.ListToList(taskInfos, TaskInfoDto.class);

        //获取执行中的任务
        Date now = new Date();
        taskInfoDtos = taskInfoDtos.stream().filter(taskInfoDto -> now.getTime() >= taskInfoDto.getStartDate().getTime() && now.getTime() <= taskInfoDto.getEndDate().getTime()).collect(Collectors.toList());
        taskIds = taskInfoDtos.stream().map(taskInfoDto -> taskInfoDto.getTaskId()).collect(Collectors.toList());
        if (CollUtil.isEmpty(taskIds)) {
            return false;
        }

        List<AssignAppDto> assignAppDtos = taskInfoMapper.listAssignAppDto(userId, taskIds);
        //获取通话记录
        List<CallRecord> callRecords = callRecordService.inquireCallRecordByUserId(CollUtil.newArrayList(userId));

        for (AssignAppDto assignAppDto : assignAppDtos) {
            List<CallRecord> callRecordsSub = callRecords.stream().filter(callRecord -> callRecord.getCustomerNo().equals(assignAppDto.getCustomerPhone())).collect(Collectors.toList());
            if (callRecordsSub.size() == 0) {
                return true;
            }
        }
        return false;
    }


    @Override
    public List<TaskInfoDto> inquireTaskInfoListByTaskState(Integer taskState, Integer userId, String taskTitle) {
        taskState = taskState == null ? 0 : taskState;

        List<TaskInfoDto> taskInfoDtos = taskInfoMapper.listTaskInfoDto(userId, taskTitle);
        if (CollectionUtil.isEmpty(taskInfoDtos)) {
            return taskInfoDtos;
        }
        List<Integer> taskIds = taskInfoDtos.stream().map(taskInfoDto -> taskInfoDto.getTaskId()).collect(Collectors.toList());

        //对任务标志进行置值
        for (TaskInfoDto taskInfoDto : taskInfoDtos) {
            if (!taskIds.contains(taskInfoDto.getTaskId())) {
                taskInfoDto.setTaskState(TaskStateEnum.READY_ASSIGN.getKey());
            } else {
                Date now = new Date();
                if (now.getTime() < taskInfoDto.getStartDate().getTime()) {
                    taskInfoDto.setTaskState(TaskStateEnum.READY_START.getKey());
                } else if (now.getTime() >= taskInfoDto.getStartDate().getTime() && now.getTime() <= taskInfoDto.getEndDate().getTime()) {
                    taskInfoDto.setTaskState(TaskStateEnum.EXECUTORY.getKey());
                } else {
                    taskInfoDto.setTaskState(TaskStateEnum.OVERDUE.getKey());
                }
            }
        }

        //对任务以状态的“进行中-未开始-已过期”进行排序
        taskInfoDtos = taskInfoDtos.stream().sorted(Comparator.comparingInt(TaskInfoDto::getTaskState)).collect(Collectors.toList());

        taskState = taskState == null ? 0 : taskState;
        //筛选进行中任务或过期任务
        if (TaskStateEnum.EXECUTORY.getKey().equals(taskState)) {
            taskInfoDtos = taskInfoDtos.stream().filter(taskInfoDto -> taskInfoDto.getTaskState().equals(TaskStateEnum.EXECUTORY.getKey())).collect(Collectors.toList());
        } else if (TaskStateEnum.OVERDUE.getKey().equals(taskState)) {
            taskInfoDtos = taskInfoDtos.stream().filter(taskInfoDto -> taskInfoDto.getTaskState().equals(TaskStateEnum.OVERDUE.getKey())).collect(Collectors.toList());
        }
        taskIds = taskInfoDtos.stream().map(taskInfoDto -> taskInfoDto.getTaskId()).collect(Collectors.toList());
        if (CollectionUtil.isEmpty(taskIds)) {
            return taskInfoDtos;
        }

        List<TaskUserRelation> relations = taskUserRelationService.list(taskIds, userId);
        Map<Integer, List<TaskUserRelation>> collect = relations.stream().collect(Collectors.groupingBy(TaskUserRelation::getTaskId));
        for (Map.Entry entry : collect.entrySet()) {
            List<TaskUserRelation> taskRelations = (List<TaskUserRelation>) entry.getValue();
            List<Integer> taskUserIds = taskRelations.stream().map(taskUserRelation -> taskUserRelation.getTaskUserId()).collect(Collectors.toList());
            //客户数量
            Set<String> customerPhones = taskRelations.stream().map(taskUserRelation -> taskUserRelation.getCustomerPhone()).collect(Collectors.toSet());
            //已呼客户数
            Integer callNum = callRecordService.countTaskCallNum(taskUserIds);
            //计算进度
            BigDecimal taskProgress = new BigDecimal(callNum).divide(new BigDecimal(customerPhones.size()), 2, BigDecimal.ROUND_HALF_UP);
            Integer taskId = (Integer) entry.getKey();
            TaskInfoDto taskInfoDto = taskInfoDtos.stream().filter(taskInfoDto1 -> taskInfoDto1.getTaskId().equals(taskId)).findFirst().get();
            taskInfoDto.setTaskProgress(taskProgress);
        }

        return taskInfoDtos;
    }


    @Override
    public CommonPage<AssignDto> inquireAssignPageList(Integer taskId, String customerNameOrPhone, String userNameOrJobNum, String sortField, String sortOrder, String phoneStatus, String customerIntentions, Integer valid, Integer pageIndex, Integer pageSize) {
        pageIndex = pageIndex == null ? 1 : pageIndex;
        pageSize = pageSize == null ? 10 : pageSize;

        List<Integer> intentionList = StringUtil.stringToIntegerList(customerIntentions);
        List<AssignDto> assignDtos = taskInfoMapper.inquireAssignPageList(valid, taskId, customerNameOrPhone, userNameOrJobNum, sortField, sortOrder, intentionList);
        List<Integer> userIds = assignDtos.stream().map(assignDto -> assignDto.getUserId()).distinct().collect(Collectors.toList());

        List<CallRecord> callRecords = new ArrayList<>();
        List<CallRecord> answerRecords = new ArrayList<>();
        if (userIds.size() > 0) {
            callRecords = callRecordService.listTaskCallRecord(taskId);
            answerRecords = callRecordService.listAnswerRecord(taskId);
        }


        //设置通话状态
        for (AssignDto assignDto : assignDtos) {
            List<CallRecord> callRecordsSub = callRecords.stream().filter(callRecord -> callRecord.getUserId().equals(assignDto.getUserId())).filter(callRecord -> callRecord.getCustomerNo().equals(assignDto.getCustomerPhone())).collect(Collectors.toList());
            if (callRecordsSub.size() == 0) {
                assignDto.setCallState(CalllStateEnum.WAIT_TO_CALL.getKey());
            } else {
                List<CallRecord> answerRecordSub = answerRecords.stream().filter(answerRecord -> answerRecord.getUserId().equals(assignDto.getUserId())).filter(answerRecord -> answerRecord.getCustomerNo().equals(assignDto.getCustomerPhone())).collect(Collectors.toList());
                if (answerRecordSub.size() == 0) {
                    assignDto.setCallState(CalllStateEnum.NOT_ANSWER.getKey());
                } else {
                    assignDto.setCallState(CalllStateEnum.ANSWER.getKey());
                }
            }
        }

        List<Integer> phoneStatusList = StringUtil.stringToIntegerList(phoneStatus);
        List<AssignDto> assignAll = new ArrayList<>();
        for (Integer status : phoneStatusList) {
            List<AssignDto> tempList = new ArrayList<>();
            //筛选出指定通话状态的分配信息
            if (CalllStateEnum.WAIT_TO_CALL.getKey().equals(status)) {
                tempList = assignDtos.stream().filter(assignAppDto -> assignAppDto.getCallState().equals(CalllStateEnum.WAIT_TO_CALL.getKey())).collect(Collectors.toList());
            } else if (CalllStateEnum.ANSWER.getKey().equals(status)) {
                tempList = assignDtos.stream().filter(assignAppDto -> assignAppDto.getCallState().equals(CalllStateEnum.ANSWER.getKey())).collect(Collectors.toList());
            } else if (CalllStateEnum.NOT_ANSWER.getKey().equals(status)) {
                tempList = assignDtos.stream().filter(assignAppDto -> assignAppDto.getCallState().equals(CalllStateEnum.NOT_ANSWER.getKey())).collect(Collectors.toList());
            }
            assignAll.addAll(tempList);
        }

        if (phoneStatusList.size() == 0) {
            assignAll.addAll(assignDtos);
        }

        Integer total = assignAll.size();
        Integer pages = total <= pageSize ? 1 : (total / pageSize == 0 ? total / pageSize : total / pageSize + 1);
        if (total > pageSize && total >= pageIndex * pageSize) {
            assignAll = assignAll.subList((pageIndex - 1) * pageSize, pageIndex * pageSize);
        } else if (total > pageSize && total < pageIndex * pageSize) {
            assignAll = assignAll.subList((pageIndex - 1) * pageSize, assignAll.size());
        }
        CommonPage commonPage = new CommonPage();
        commonPage.setPageSize(pageSize);
        commonPage.setPageNum(pageIndex);
        commonPage.setTotal(Long.valueOf(total));
        commonPage.setPages(pages);
        commonPage.setList(assignAll);

        return commonPage;
    }

    @Override
    public List<AssignAppDto> inquireAssignAppList(Integer userId, Integer taskId, String customerNameOrPhone, Integer callState, Integer userTagId) {
        List<AssignAppDto> assignAppDtos = taskInfoMapper.inquireAssignAppList(userId, taskId, customerNameOrPhone, userTagId);
        assignAppDtos.forEach(assignAppDto -> {
            String tagIds = assignAppDto.getUserTagIds();
            if (StrUtil.isNotBlank(tagIds)) {
                List<Integer> tagIdInts = StringUtil.stringToIntegerList(tagIds);
                List<UserTagDto> userTagDtos = userTagService.inquireUserTagList(tagIdInts);
                assignAppDto.setUserTagDtos(userTagDtos);
            }
        });

        List<CallRecord> callRecords = callRecordService.listTaskCallRecord(taskId);
        List<CallRecord> answerRecords = callRecordService.listAnswerRecord(taskId);

        //设置通话状态
        for (AssignAppDto assignAppDto : assignAppDtos) {
            List<CallRecord> callRecordsSub = callRecords.stream().filter(callRecord -> callRecord.getUserId().equals(assignAppDto.getUserId())).filter(callRecord -> callRecord.getCustomerNo().equals(assignAppDto.getCustomerPhone())).collect(Collectors.toList());
            if (callRecordsSub.size() == 0) {
                assignAppDto.setCallState(CalllStateEnum.WAIT_TO_CALL.getKey());
            } else {
                List<CallRecord> answerRecordSub = answerRecords.stream().filter(answerRecord -> answerRecord.getUserId().equals(assignAppDto.getUserId())).filter(answerRecord -> answerRecord.getCustomerNo().equals(assignAppDto.getCustomerPhone())).collect(Collectors.toList());
                if (answerRecordSub.size() == 0) {
                    assignAppDto.setCallState(CalllStateEnum.NOT_ANSWER.getKey());
                } else {
                    assignAppDto.setCallState(CalllStateEnum.ANSWER.getKey());
                }
            }
        }

        callState = callState == null ? 0 : callState;
        //筛选出指定通话状态的分配信息
        if (CalllStateEnum.WAIT_TO_CALL.getKey().equals(callState)) {
            assignAppDtos = assignAppDtos.stream().filter(assignAppDto -> assignAppDto.getCallState().equals(CalllStateEnum.WAIT_TO_CALL.getKey())).collect(Collectors.toList());
        } else if (CalllStateEnum.ANSWER.getKey().equals(callState)) {
            assignAppDtos = assignAppDtos.stream().filter(assignAppDto -> assignAppDto.getCallState().equals(CalllStateEnum.ANSWER.getKey())).collect(Collectors.toList());
        } else if (CalllStateEnum.NOT_ANSWER.getKey().equals(callState)) {
            assignAppDtos = assignAppDtos.stream().filter(assignAppDto -> assignAppDto.getCallState().equals(CalllStateEnum.NOT_ANSWER.getKey())).collect(Collectors.toList());
        }

        return assignAppDtos;
    }

    @Override
    public AssignDetailAppDto loadAssignAppDetail(Integer userId, Integer taskUserId) {
        TaskUserRelation taskUserRelation = taskUserRelationService.loadTaskUser(taskUserId);
        AssignDetailAppDto assignDetailAppDto = FastJsonUtil.ObjectToObject(taskUserRelation, AssignDetailAppDto.class);
        setTaskState(assignDetailAppDto);

        //获取通话详情
        List<TaskUserCall> taskUserCalls = taskUserCallService.inquireTaskUserCallList(taskUserId);
        List<TaskUserCallDto> taskUserCallDtos = FastJsonUtil.ListToList(taskUserCalls, TaskUserCallDto.class);
        taskUserCallDtos = taskUserCallDtos.stream().filter(taskUserCallDto -> Objects.nonNull(taskUserCallDto.getCallRecordId())).collect(Collectors.toList());

        taskUserCallDtos.forEach(taskUserCallDto -> {
            CallRecord callRecord = callRecordService.get(taskUserCallDto.getCallRecordId());
            if (callRecord != null) {
                taskUserCallDto.setDurationTime(callRecord.getDurationTime());
                taskUserCallDto.setPhoneStatus(callRecord.getPhoneStatus());
                taskUserCallDto.setCallid(callRecord.getCallid());
            }
        });

        //获取短信记录
        List<TaskUserMessageDto> taskUserMessageDtos = messageService.list(taskUserId);

        //获取笔记信息
        List<TaskUserNote> taskUserNotes = taskUserNoteService.inquireTaskUserNoteList(taskUserId);
        List<TaskUserNoteDto> taskUserNoteDtos = FastJsonUtil.ListToList(taskUserNotes, TaskUserNoteDto.class);

        //获取客户所在的任务
        List<CustomerTaskDto> customerTaskDtos = taskUserRelationService.inquireCustomerTaskList(userId, taskUserRelation.getCustomerPhone());

        List<UserTagDto> userTagDtos = new ArrayList<>();
        if (StrUtil.isNotBlank(taskUserRelation.getUserTagIds())) {
            List<Integer> tagIds = StringUtil.stringToIntegerList(taskUserRelation.getUserTagIds());
            userTagDtos = userTagService.inquireUserTagList(tagIds);
        }

        assignDetailAppDto.setUserCallDtoList(taskUserCallDtos);
        assignDetailAppDto.setUserMessageDtoList(taskUserMessageDtos);
        assignDetailAppDto.setUserNoteDtoList(taskUserNoteDtos);
        assignDetailAppDto.setCustomerTaskDtos(customerTaskDtos);
        assignDetailAppDto.setUserTagDtos(userTagDtos);
        return assignDetailAppDto;
    }

    private void setTaskState(AssignDetailAppDto assignDetailAppDto) {
        TaskInfo taskInfo = taskInfoMapper.selectByPrimaryKey(assignDetailAppDto.getTaskId());
        Date now = new Date();
        if (now.getTime() < taskInfo.getStartDate().getTime()) {
            assignDetailAppDto.setTaskState(TaskStateEnum.READY_START.getKey());
        } else if (now.getTime() >= taskInfo.getStartDate().getTime() && now.getTime() <= taskInfo.getEndDate().getTime()) {
            assignDetailAppDto.setTaskState(TaskStateEnum.EXECUTORY.getKey());
        } else {
            assignDetailAppDto.setTaskState(TaskStateEnum.OVERDUE.getKey());
        }
    }

    @Override
    public List<AssignDetailDto> loadAssignDetail(Integer taskUserId) {
        TaskUserRelation taskUserRelation = taskUserRelationService.loadTaskUser(taskUserId);
        List<AssignDetailDto> assignDetailDtos = new ArrayList<>();

        //获取通话详情
        List<TaskUserCall> taskUserCalls = taskUserCallService.inquireTaskUserCallList(taskUserId);
        List<TaskUserCallDto> taskUserCallDtos = FastJsonUtil.ListToList(taskUserCalls, TaskUserCallDto.class);
        taskUserCallDtos.forEach(taskUserCallDto -> {
            CallRecord callRecord = callRecordService.loadCallRecordByUserIdCustomerNo(taskUserRelation.getUserId(), taskUserRelation.getCustomerPhone(), taskUserCallDto.getOperationTime());
            if (callRecord != null) {
                taskUserCallDto.setDurationTime(callRecord.getDurationTime());
                taskUserCallDto.setPhoneStatus(callRecord.getPhoneStatus());
            }
        });
        for (TaskUserCallDto taskUserCallDto : taskUserCallDtos) {
            AssignDetailDto assignDetailDto = new AssignDetailDto();
            assignDetailDto.setOperationType("呼叫");
            assignDetailDto.setOperationTime(taskUserCallDto.getOperationTime());
            if (taskUserCallDto.getPhoneStatus() != null) {
                if (taskUserCallDto.getPhoneStatus().equals(PhoneStateEnum.ANSWER.getKey())) {
                    assignDetailDto.setOperationDetail("呼叫了该客户，通话时长" + taskUserCallDto.getDurationTime() + "s");
                } else {
                    assignDetailDto.setOperationDetail("呼叫了该客户，未接通");
                }
            } else {
                continue;
            }

            assignDetailDtos.add(assignDetailDto);
        }

        //获取短信记录
        List<TaskUserMessage> taskUserMessages = taskUserMessageService.inquireTaskUserMessage(taskUserId);
        for (TaskUserMessage taskUserMessage : taskUserMessages) {
            AssignDetailDto assignDetailDto = new AssignDetailDto();
            assignDetailDto.setOperationType("发送短信");
            assignDetailDto.setOperationTime(taskUserMessage.getOperationTime());
            assignDetailDto.setOperationDetail(taskUserMessage.getContent());
            assignDetailDtos.add(assignDetailDto);
        }

        //获取笔记信息
        List<TaskUserNote> taskUserNotes = taskUserNoteService.inquireTaskUserNoteList(taskUserId);
        for (TaskUserNote taskUserNote : taskUserNotes) {
            AssignDetailDto assignDetailDto = new AssignDetailDto();
            assignDetailDto.setOperationType("记笔记");
            assignDetailDto.setOperationTime(taskUserNote.getOperationTime());
            assignDetailDto.setOperationDetail(taskUserNote.getContent());
            assignDetailDtos.add(assignDetailDto);
        }

        assignDetailDtos = assignDetailDtos.stream().sorted(Comparator.comparingLong(a -> a.getOperationTime().getTime())).collect(Collectors.toList());
        return assignDetailDtos;
    }

    @Override
    @Transactional
    public ImportTaskDto importTaskTemplateExcel(Integer taskId, ModelMap map, HttpServletRequest request, HttpServletResponse response, MultipartFile file, Integer flag) throws Exception {
        ImportParams importParams = new ImportParams();
        importParams.setTitleRows(1);
        importParams.setHeadRows(1);
        List<TaskTemplateExcel> taskTemplateExcels = ExcelImportUtil.importExcel(file.getInputStream(), TaskTemplateExcel.class, importParams);

        //TaskTemplateExcel筛选
        taskTemplateExcels = processTaskTemplateExcel(taskTemplateExcels);

        List<String> jobNums = taskTemplateExcels.stream().map(taskTemplateExcel -> taskTemplateExcel.getJobNum()).distinct().collect(Collectors.toList());

        //给TaskTemplateExcel相关参数置值
        int count = setTaskTemplateExcel(taskId, jobNums, taskTemplateExcels);

        int insertCount = 0;
        flag = flag == null ? 0 : flag;
        if (flag == 1) {
            //将有问题的信息排除
            List<TaskTemplateExcel> taskTemplateExcelsList = taskTemplateExcels.stream().filter(userTemplateExcel -> StrUtil.isBlank(userTemplateExcel.getErrorInfo())).collect(Collectors.toList());
            if (taskTemplateExcelsList.isEmpty()) {
                return new ImportTaskDto(insertCount, count, taskTemplateExcels);
            }

            if (taskTemplateExcelsList.size() > 0) {
                insertCount = batchCreateTask(taskId, taskTemplateExcelsList);
            }
        } else {
            if (count == 0) {
                insertCount = batchCreateTask(taskId, taskTemplateExcels);
            }
        }

        //返回数据
        ImportTaskDto importTaskDto = new ImportTaskDto();
        importTaskDto.setSuccessNumber(insertCount);
        importTaskDto.setFailureNumber(count);
        taskTemplateExcels = taskTemplateExcels.stream().filter(taskTemplateExcel -> StrUtil.isNotBlank(taskTemplateExcel.getErrorInfo())).collect(Collectors.toList());
        importTaskDto.setTaskTemplateExcels(taskTemplateExcels);
        return importTaskDto;
    }

    private int setTaskTemplateExcel(Integer taskId, List<String> jobNums, List<TaskTemplateExcel> taskTemplateExcels) {
        TaskInfo taskInfo = taskInfoMapper.selectByPrimaryKey(taskId);
        List<UserInfo> userInfoList = userInfoService.listSubByDepartmentId(taskInfo.getDepartmentId());
        //获取任务所属部门下的员工工号
        List<String> jobNumInDepartment = userInfoList.stream().map(userInfoDto -> userInfoDto.getJobNum()).collect(Collectors.toList());
        //查询数据库中已存在的工号
        List<String> jobNumDB = userInfoService.inquireUserInfoByJobNum(jobNums);
        //获取传参中不存在的工号
        List<String> missingList = GeneralUtil.getMissingList(jobNumDB, jobNums);
        int count = 0;
        for (int i = 0; i < taskTemplateExcels.size(); i++) {
            TaskTemplateExcel taskTemplateExcel = taskTemplateExcels.get(i);
            if (missingList.contains(taskTemplateExcel.getJobNum())) {
                taskTemplateExcel.setErrorInfo("该工号不存在;");
                count++;
                continue;
            }
            if (!jobNumInDepartment.contains(taskTemplateExcel.getJobNum())) {
                taskTemplateExcel.setErrorInfo("该员工不属于该任务的所属部门;");
                count++;
                continue;
            }
        }

        taskTemplateExcels.forEach(taskTemplateExcel -> {
            if (StrUtil.isBlank(taskTemplateExcel.getCustomerName())) {
                taskTemplateExcel.setCustomerName("******");
            }
            taskTemplateExcel.setJobNum(StrUtil.trim(taskTemplateExcel.getJobNum()));
        });

        //设置userId
        List<UserInfo> userInfos = userInfoService.inquireUserIdByJobNum(jobNums);
        taskTemplateExcels.forEach(taskTemplateExcel -> {
            userInfos.forEach(userInfo -> {
                if (taskTemplateExcel.getJobNum().equals(userInfo.getJobNum())) {
                    taskTemplateExcel.setUserId(userInfo.getUserId());
                }
            });
        });
        return count;
    }

    private List<TaskTemplateExcel> processTaskTemplateExcel(List<TaskTemplateExcel> taskTemplateExcels) {
        taskTemplateExcels = taskTemplateExcels.stream()
                .filter(taskTemplateExcel -> StrUtil.isNotBlank(taskTemplateExcel.getCustomerPhone()))
                .collect(Collectors.toList());
        //客户电话去重
        Map<String, List<TaskTemplateExcel>> collects = taskTemplateExcels.stream().collect(Collectors.groupingBy(taskTemplateExcel -> taskTemplateExcel.getCustomerPhone()));
        taskTemplateExcels = new ArrayList<>();
        for (Map.Entry entry : collects.entrySet()) {
            List<TaskTemplateExcel> excels = (List<TaskTemplateExcel>) entry.getValue();
            if (excels.size() == 1) {
                taskTemplateExcels.addAll(excels);
            } else {
                taskTemplateExcels.add(excels.get(0));
            }
        }
        return taskTemplateExcels;
    }

    @Override
    public void exportAssignInfo(Integer taskId, ModelMap map, HttpServletRequest request, HttpServletResponse response) {
        CommonPage<AssignDto> assignDtoPageInfo = inquireAssignPageList(taskId, null, null, null, null, null, null, null, 1, 999);
        List<TaskAssignInfoExcel> assignInfoExcels = FastJsonUtil.ListToList(assignDtoPageInfo.getList(), TaskAssignInfoExcel.class);
        assignInfoExcels.forEach(assignInfoExcel -> {
            String state = assignInfoExcel.getCallState();
            state = state.equals("1") ? "待呼" : (state.equals("2") ? "已通" : "3未接");
            assignInfoExcel.setCallState(state);
        });

        ExportParams params = new ExportParams("分配详情", "分配详情", ExcelType.XSSF);
        map.put(NormalExcelConstants.DATA_LIST, assignInfoExcels);
        map.put(NormalExcelConstants.CLASS, TaskAssignInfoExcel.class);
        map.put(NormalExcelConstants.PARAMS, params);
        map.put(NormalExcelConstants.FILE_NAME, "分配详情");
        PoiBaseView.render(map, request, response, NormalExcelConstants.EASYPOI_EXCEL_VIEW);
    }

    private int batchCreateTask(Integer taskId, List<TaskTemplateExcel> taskTemplateExcels) {
        List<String> customerPhones = taskTemplateExcels.stream().map(taskTemplateExcel -> taskTemplateExcel.getCustomerPhone()).collect(Collectors.toList());
        List<TaskUserRelation> updateTaskUserRelations = taskUserRelationService.list(taskId, customerPhones);
        List<String> customerPhoneDb = updateTaskUserRelations.stream().map(taskUserRelation -> taskUserRelation.getCustomerPhone()).collect(Collectors.toList());


        for (TaskUserRelation taskUserRelation : updateTaskUserRelations) {
            for (TaskTemplateExcel taskTemplateExcel : taskTemplateExcels) {
                if (taskUserRelation.getCustomerPhone().equals(taskTemplateExcel.getCustomerPhone())) {
                    taskUserRelation.setUserId(taskTemplateExcel.getUserId());
                    break;
                }
            }
        }
        if (CollectionUtil.isNotEmpty(updateTaskUserRelations)){
            taskUserRelationService.updateBatch(updateTaskUserRelations);
        }

        taskTemplateExcels = taskTemplateExcels.stream().filter(taskTemplateExcel -> !customerPhoneDb.contains(taskTemplateExcel.getCustomerPhone())).collect(Collectors.toList());
        if (CollectionUtil.isEmpty(taskTemplateExcels)){
            return 0;
        }
        List<TaskUserRelation> taskUserRelations = FastJsonUtil.ListToList(taskTemplateExcels, TaskUserRelation.class);
        Date now = new Date();
        taskUserRelations.forEach(taskUserRelation -> {
            taskUserRelation.setTaskId(taskId);
            taskUserRelation.setTaskTime(now);
            taskUserRelation.setCustomerIntention(0);
            taskUserRelation.setValid(ValidEnum.VALID.getKey());
            taskUserRelation.setTop(0);
        });
        return taskUserRelationService.createTaskUserRelationBatch(taskUserRelations);
    }

    @Override
    @Async
    public Future<Integer> count() {
        return new AsyncResult<>(taskInfoMapper.count());
    }

    @Override
    @Async
    public Future<Integer> countExecutory() {
        List<TaskInfo> taskInfos = taskInfoMapper.find();
        List<Integer> taskIds = taskUserRelationService.getTaskId();
        Date now = new Date();
        taskInfos = taskInfos.stream()
                .filter(taskInfo -> taskIds.contains(taskInfo.getTaskId()))
                .filter(taskInfo -> now.getTime() >= taskInfo.getStartDate().getTime() && now.getTime() <= taskInfo.getEndDate().getTime())
                .collect(Collectors.toList());
        return new AsyncResult<>(taskInfos.size());
    }

    @Override
    @Async
    public Future<Integer> countReadyAssign() {
        List<TaskInfo> taskInfos = taskInfoMapper.find();
        List<Integer> taskIds = taskUserRelationService.getTaskId();
        Date now = new Date();
        taskInfos = taskInfos.stream()
                .filter(taskInfo -> !taskIds.contains(taskInfo.getTaskId()))
                .collect(Collectors.toList());
        return new AsyncResult<>(taskInfos.size());
    }

    @Override
    @Async
    public Future<Integer> countReadyStart() {
        List<TaskInfo> taskInfos = taskInfoMapper.find();
        List<Integer> taskIds = taskUserRelationService.getTaskId();
        Date now = new Date();
        taskInfos = taskInfos.stream()
                .filter(taskInfo -> taskIds.contains(taskInfo.getTaskId()))
                .filter(taskInfo -> now.getTime() < taskInfo.getStartDate().getTime())
                .collect(Collectors.toList());
        return new AsyncResult<>(taskInfos.size());
    }

    @Override
    @Async
    public Future<Integer> countOverdue() {
        List<TaskInfo> taskInfos = taskInfoMapper.find();
        List<Integer> taskIds = taskUserRelationService.getTaskId();
        Date now = new Date();
        taskInfos = taskInfos.stream()
                .filter(taskInfo -> taskIds.contains(taskInfo.getTaskId()))
                .filter(taskInfo -> now.getTime() > taskInfo.getEndDate().getTime())
                .collect(Collectors.toList());
        return new AsyncResult<>(taskInfos.size());
    }

    @Override
    public List<TaskInfo> list(Collection<Integer> taskIds) {
        return taskInfoMapper.findByTaskIdIn(taskIds);
    }

    @Override
    @Async
    public Future<List<TaskIndexDto>> listTaskIndexDto() {
        return new AsyncResult<>(taskInfoMapper.listTaskIndexDto());
    }

    @Override
    @Async
    public Future<Integer> countCustomer() {
        return new AsyncResult<>(taskInfoMapper.countCustomer());
    }
}
